//
// Created by xuzhou4 on 2021/12/27.
//

#include "audioutils.h"

int mp3ToFlac(const char *sourcePath, const char *destPath) {
    LOGE("source path : %s -> %s", sourcePath, destPath);

    AVFormatContext *avFormatContext = avformat_alloc_context();

    int ret = avformat_open_input(&avFormatContext, sourcePath, NULL, NULL);
    if (ret != 0) {
        LOGE("format open input error %i", ret);
        return FORMAT_OPEN_FAIL;
    }

    ret = avformat_find_stream_info(avFormatContext, NULL);
    if (ret != 0) {
        LOGE("format find stream info error %i", ret);
        return STREAM_NOT_FOUND;
    }

    unsigned int streamCount = avFormatContext->nb_streams;
    int streamIndex = -1;
    AVCodecID avCodecId = AV_CODEC_ID_MP3;
    for (int i = 0; i < streamCount; ++i) {
        if (avFormatContext->streams[i]->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&
            (avFormatContext->streams[i]->codecpar->codec_id == AV_CODEC_ID_MP3 ||
             avFormatContext->streams[i]->codecpar->codec_id == AV_CODEC_ID_MP3ADU ||
             avFormatContext->streams[i]->codecpar->codec_id == AV_CODEC_ID_MP3ON4 ||
             avFormatContext->streams[i]->codecpar->codec_id == AV_CODEC_ID_MPEGH_3D_AUDIO)) {
            if (streamIndex != -1) {
                LOGE("find mush streams of mp3 error");
                return STREAM_MP3_NOT_FOUND;
            }
            streamIndex = i;
        }
    }

    if (streamIndex == -1) {
        LOGE("not find stream of mp3");
        return STREAM_MP3_NOT_FOUND;
    }

    LOGD("find mp3 stream, index %i", streamIndex);

    AVCodec *avCodec = avcodec_find_decoder(avCodecId);
    if (avCodec == NULL) {
        LOGD("not find codec, codecId %i", avCodecId);
        return CODEC_NOT_FOUND;
    }

    AVCodecContext *avCodecContext = avcodec_alloc_context3(avCodec);
    ret = avcodec_open2(avCodecContext, avCodec, NULL);
    if (ret != 0) {
        LOGE("av codec open fail %i", ret);
        return CODEC_OPEN_FAIL;
    }

    AVPacket *avPacket = av_packet_alloc();
    while ((ret = av_read_frame(avFormatContext, avPacket)) == 0) {
        LOGD("read frame ret : %i", ret);

        avcodec_send_packet(avCodecContext, avPacket);
    }
    LOGD("read frame ret : %i", ret);

    return 0;
}